package cz.vutbr.fit.xzemko01.tfmcbs.validation.validators;

import java.util.Map;

import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;

import cz.vutbr.fit.xzemko01.tfmcbs.model.CompositeComponent;
import cz.vutbr.fit.xzemko01.tfmcbs.model.Requier;
import cz.vutbr.fit.xzemko01.tfmcbs.model.RequiringPort;
import cz.vutbr.fit.xzemko01.tfmcbs.model.SimpleComponent;
import cz.vutbr.fit.xzemko01.tfmcbs.model.Usage;
import cz.vutbr.fit.xzemko01.tfmcbs.validation.utils.DiagnosticBuilder;

public class RequierValidator implements Validator<Requier>  {
	
	private static RequierValidator requierValidator;
	
	private RequierValidator() {
	}
	
	public static Validator<Requier> getInstance() {
		if(requierValidator == null) {
			requierValidator = new RequierValidator();
		}
		
		return requierValidator;
	}

	@Override
	public boolean validate(Requier requier, DiagnosticChain diagnostics, Map<Object, Object> context) {
		boolean result = validateUniqueUsage(requier, diagnostics, context);
		return result;
	}
	
	private boolean validateUniqueUsage(Requier requier, DiagnosticChain diagnostics, Map<Object, Object> context) {
		if(requier == null || requier.getUsages() == null) {
			return true;
		}
		
		int i = 0;
		boolean result = true;
		
		for(Usage usage1 : requier.getUsages()) {
			i++;
			for(int j = i; j < requier.getUsages().size(); j++) {
				Usage usage2 = requier.getUsages().get(j);
				
				if(usage1.getInterface() != null
						&& usage2.getInterface() != null
						&& usage1.getInterface() == usage2.getInterface()) 
				{
					String errorMessage = "";
					if(requier instanceof SimpleComponent) {
						errorMessage += "Component \"" + ((SimpleComponent) requier).getName() + "\" ";
					} else if(requier instanceof RequiringPort) {
						RequiringPort port = (RequiringPort) requier;
						errorMessage += "Port \"" + port.getName() + "\"";
						
						CompositeComponent component = port.getComponent();
						if(component != null) {
							errorMessage += " in the component \"" + component.getName() + "\"";
						}
					}
					
					errorMessage += "use interface \"" + usage1.getInterface().getName() + "\" two or more times.";
					
					Diagnostic diagnostic = 
							new DiagnosticBuilder(requier).setMessage(errorMessage).build();
					
					diagnostics.add(diagnostic);
					result = false;
				}
			}
		}
		return result;
	}
}
